﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using FFmpegVideoClip.Configuration;
using FFmpegVideoClip.Processing;

namespace FFmpegVideoClip.Lib.TaskFlowProcessor
{

    public class SplitTaskFlow: TaskFlowAbstract
    {
        private Window? m_Window;
        public SplitTaskFlow() { }
        public SplitTaskFlow(Action<double, double> ProgressChangeEvent, Window? window = null)
        {
            OnProgressChange = ProgressChangeEvent;
            m_Window = window;
        }
        private Dictionary<Clip, LosslessSplitTask[]>? dic;
        public override object? Data => dic;

        private bool IsComplete = false;
        private double TotalSeconds;
        public override void Execute(List<TaskFlowAbstract> FlowList, TaskFlowAbstract? Previous, params object[] args)
        {
            if (args.Length < 0 || args[0] is not bool EnableKeyframe)
                throw new ArgumentException($"参数错误：[{nameof(SplitTaskFlow)}] 分割处理需要在参数数组的索引位置[0]中,传入一个[bool类型]的[{nameof(EnableKeyframe)}](是否启用关键帧),以确定是否使用关键帧模式 ");

            if (clips == null)
                return;

            dic = clips.Where(clip => 
            {
                if( clip.Count < 1)
                    return false;
                try
                {
                    foreach(Fragment fragment in clip.Fragments)
                        fragment.GenerateTempWritePath();
                    return true;
                }
                catch (Exception exc)
                {
                   m_Window?.Dispatcher.BeginInvoke(() => MessageBoxEx.Show(m_Window, exc.Message, "分割异常", MessageBoxButton.OK, MessageBoxImage.Error));
                    return false;
                }
            }).Select(clip => new KeyValuePair<Clip, LosslessSplitTask[]>(clip, clip.Fragments.Select(fragment => new LosslessSplitTask(fragment, EnableKeyframe)).Where(p=>p is not null).ToArray()))
              .ToDictionary(k => k.Key, v => v.Value);
            IsComplete = false;
            CalculateProgress();
            try
            {
                Parallel.ForEach(dic.SelectMany(k => k.Value), new ParallelOptions { MaxDegreeOfParallelism = Config.MaxThread, CancellationToken = Tools.CurrentCancelToken!.Token }, p => p.Execute());
                IsError = false;
            }
            catch (OperationCanceledException) { }
            catch (Exception exc)
            {
                LogManage.WriteExceptionInfo($"[{nameof(SplitTaskFlow)}] 异常：", exc, true);
            }
            finally { IsComplete = true; }
            
        }
        
        private void CalculateProgress()
        {
           LosslessSplitTask[]? tasks =  dic?.SelectMany(p => p.Value).ToArray();
           TotalSeconds = tasks?.Sum(p => ((Fragment)p.SourceData!).FragmentDuration.TotalSeconds)?? 0;
            Task.Run(() => 
            {
                while (!IsComplete)
                {
                    //OnProgressChange?.Invoke(TotalSeconds,(TotalSeconds - (tasks?.Sum(p => p.ProcessorTime.TotalSeconds) ?? 0)) / TotalSeconds);
                    OnProgressChange?.Invoke(TotalSeconds,tasks?.Sum(p => p.ProcessorTime.TotalSeconds) ?? 0);
                    Thread.Sleep(1000);
                }
            });
        }
    }


}
